/**
 * 角色数据模型
 * 负责处理角色相关的数据库操作
 * 包括角色的增删改查、角色菜单关联等功能
 */
import { pool } from "../config/database.js";

class Role {
	/**
	 * 创建新角色
	 * @param {Object} roleData - 角色数据对象
	 * @param {string} roleData.name - 角色名称
	 * @param {string} roleData.code - 角色编码
	 * @param {string} [roleData.description] - 角色描述
	 * @param {number} [roleData.status=1] - 状态(0:禁用,1:启用)，默认为1
	 * @returns {Promise<Object>} 创建的角色对象，包含生成的ID
	 * @throws {Error} 数据库操作错误
	 */
	static async create(roleData) {
		try {
			const [result] = await pool.execute(
				"INSERT INTO roles (name, code, description, status, created_at) VALUES (?, ?, ?, ?, NOW())",
				[
					roleData.name,
					roleData.code,
					roleData.description || null,
					roleData.status === undefined ? 1 : roleData.status,
				]
			);
			return { id: result.insertId, ...roleData };
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 通过ID查找角色
	 * @param {number} id - 角色ID
	 * @returns {Promise<Object|null>} 角色对象，如果不存在返回null
	 * @throws {Error} 数据库操作错误
	 */
	static async findById(id) {
		try {
			const [rows] = await pool.execute(
				"SELECT id, name, code, description, status, created_at, updated_at FROM roles WHERE id = ? AND is_deleted = 0",
				[id]
			);
			return rows[0];
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 通过编码查找角色
	 * @param {string} code - 角色编码
	 * @returns {Promise<Object|null>} 角色对象，如果不存在返回null
	 * @throws {Error} 数据库操作错误
	 */
	static async findByCode(code) {
		try {
			const [rows] = await pool.execute(
				"SELECT id, name, code, description, status, created_at, updated_at FROM roles WHERE code = ? AND is_deleted = 0",
				[code]
			);
			return rows[0];
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 检查角色名称是否已存在
	 * @param {string} name - 角色名称
	 * @param {number} [excludeId] - 排除的角色ID（用于更新时检查）
	 * @returns {Promise<boolean>} 如果存在返回true，否则返回false
	 * @throws {Error} 数据库操作错误
	 */
	static async isNameExist(name, excludeId = 0) {
		try {
			let sql = "SELECT COUNT(*) as count FROM roles WHERE name = ? AND is_deleted = 0";
			let params = [name];

			if (excludeId > 0) {
				sql += " AND id != ?";
				params.push(excludeId);
			}

			const [rows] = await pool.execute(sql, params);
			return rows[0].count > 0;
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 检查角色编码是否已存在
	 * @param {string} code - 角色编码
	 * @param {number} [excludeId] - 排除的角色ID（用于更新时检查）
	 * @returns {Promise<boolean>} 如果存在返回true，否则返回false
	 * @throws {Error} 数据库操作错误
	 */
	static async isCodeExist(code, excludeId = 0) {
		try {
			let sql = "SELECT COUNT(*) as count FROM roles WHERE code = ? AND is_deleted = 0";
			let params = [code];

			if (excludeId > 0) {
				sql += " AND id != ?";
				params.push(excludeId);
			}

			const [rows] = await pool.execute(sql, params);
			return rows[0].count > 0;
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 更新角色信息
	 * @param {number} id - 角色ID
	 * @param {Object} roleData - 要更新的角色数据
	 * @returns {Promise<Object>} 更新后的角色对象
	 * @throws {Error} 数据库操作错误或角色不存在
	 */
	static async update(id, roleData) {
		try {
			// 构建更新字段和参数
			const updateFields = [];
			const params = [];

			if (roleData.name !== undefined) {
				updateFields.push("name = ?");
				params.push(roleData.name);
			}

			if (roleData.code !== undefined) {
				updateFields.push("code = ?");
				params.push(roleData.code);
			}

			if (roleData.description !== undefined) {
				updateFields.push("description = ?");
				params.push(roleData.description);
			}

			if (roleData.status !== undefined) {
				updateFields.push("status = ?");
				params.push(roleData.status);
			}

			// 如果没有要更新的字段，直接返回
			if (updateFields.length === 0) {
				return await this.findById(id);
			}

			// 添加ID参数
			params.push(id);

			// 执行更新
			const [result] = await pool.execute(
				`UPDATE roles SET ${updateFields.join(", ")} WHERE id = ? AND is_deleted = 0`,
				params
			);

			if (result.affectedRows === 0) {
				throw new Error("角色不存在或已被删除");
			}

			// 返回更新后的角色
			return await this.findById(id);
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 删除角色（软删除）
	 * @param {number} id - 角色ID
	 * @returns {Promise<boolean>} 删除成功返回true
	 * @throws {Error} 数据库操作错误或角色不存在
	 */
	static async delete(id) {
		try {
			const [result] = await pool.execute(
				"UPDATE roles SET is_deleted = 1 WHERE id = ? AND is_deleted = 0",
				[id]
			);

			if (result.affectedRows === 0) {
				throw new Error("角色不存在或已被删除");
			}

			return true;
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 获取角色列表
	 * @param {Object} options - 查询选项
	 * @param {number} [options.page=1] - 页码
	 * @param {number} [options.limit=10] - 每页数量
	 * @param {string} [options.name] - 按名称筛选
	 * @param {string} [options.code] - 按编码筛选
	 * @param {number} [options.status] - 按状态筛选
	 * @returns {Promise<Object>} 包含角色列表和总数的对象
	 * @throws {Error} 数据库操作错误
	 */
	static async findAll(options = {}) {
		try {
			const page = options.page || 1;
			const limit = options.limit || 10;
			const offset = (page - 1) * limit;

			// 构建查询条件
			let whereClause = "WHERE is_deleted = 0";
			const params = [];

			if (options.name) {
				whereClause += " AND name LIKE ?";
				params.push(`%${options.name}%`);
			}

			if (options.code) {
				whereClause += " AND code LIKE ?";
				params.push(`%${options.code}%`);
			}

			if (options.status !== undefined) {
				whereClause += " AND status = ?";
				params.push(options.status);
			}

			// 查询总数
			const [countRows] = await pool.execute(
				`SELECT COUNT(*) as total FROM roles ${whereClause}`,
				params
			);
			const total = countRows[0].total;

			// 查询数据
			const queryParams = [...params, offset, limit];
			const [rows] = await pool.execute(
				`SELECT id, name, code, description, status, created_at, updated_at 
				FROM roles ${whereClause} 
				ORDER BY created_at DESC 
				LIMIT ?, ?`,
				queryParams
			);

			return {
				list: rows,
				total,
				page,
				limit,
			};
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 为角色分配菜单
	 * @param {number} roleId - 角色ID
	 * @param {Array<number>} menuIds - 菜单ID数组
	 * @returns {Promise<boolean>} 分配成功返回true
	 * @throws {Error} 数据库操作错误
	 */
	static async assignMenus(roleId, menuIds) {
		try {
			// 开始事务
			const connection = await pool.getConnection();
			await connection.beginTransaction();

			try {
				// 删除原有的角色菜单关联
				await connection.execute(
					"DELETE FROM role_menus WHERE role_id = ?",
					[roleId]
				);

				// 如果有新的菜单ID，则插入新的关联
				if (menuIds && menuIds.length > 0) {
					// 构建批量插入的值
					const values = menuIds.map(menuId => `(${roleId}, ${menuId})`).join(", ");
					
					// 执行批量插入
					await connection.execute(
						`INSERT INTO role_menus (role_id, menu_id) VALUES ${values}`
					);
				}

				// 提交事务
				await connection.commit();
				return true;
			} catch (error) {
				// 回滚事务
				await connection.rollback();
				throw error;
			} finally {
				// 释放连接
				connection.release();
			}
		} catch (error) {
			throw error;
		}
	}

	/**
	 * 获取角色的菜单ID列表
	 * @param {number} roleId - 角色ID
	 * @returns {Promise<Array<number>>} 菜单ID数组
	 * @throws {Error} 数据库操作错误
	 */
	static async getRoleMenuIds(roleId) {
		try {
			const [rows] = await pool.execute(
				"SELECT menu_id FROM role_menus WHERE role_id = ?",
				[roleId]
			);
			return rows.map(row => row.menu_id);
		} catch (error) {
			throw error;
		}
	}
}

export default Role;